package com.deyuanyun.pic.pbf.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deyuanyun.pic.common.cache.TempStoreDataSupport;
import com.deyuanyun.pic.common.util.CommonUtil;
import com.deyuanyun.pic.common.util.DateUtil;
import com.deyuanyun.pic.common.util.ObjectUtil;
import com.deyuanyun.pic.common.util.StringUtils;
import com.deyuanyun.pic.common.util.web.Asserts;
import com.deyuanyun.pic.common.webservice.UtilsServiceClient;
import com.deyuanyun.pic.ctrl.domain.ExinspOclpoint;
import com.deyuanyun.pic.ctrl.domain.RecodeTask;
import com.deyuanyun.pic.ctrl.mapper.ExinspOclpointMapper;
import com.deyuanyun.pic.ctrl.mapper.RecodeTaskMapper;
import com.deyuanyun.pic.pbf.app.domain.*;
import com.deyuanyun.pic.pbf.app.enumeration.ConfigCode;
import com.deyuanyun.pic.pbf.app.enumeration.DefectTypeCode;
import com.deyuanyun.pic.pbf.app.enumeration.FormCode;
import com.deyuanyun.pic.pbf.app.enumeration.PbfAppCode;
import com.deyuanyun.pic.pbf.app.mapper.PbfMapper;
import com.deyuanyun.pic.pbf.app.service.PbfService;
import com.deyuanyun.pic.pbf.domain.*;
import com.deyuanyun.pic.pbf.enumeration.DefectStateEnum;
import com.deyuanyun.pic.pbf.enumeration.RepairStateEnum;
import com.deyuanyun.pic.pbf.mapper.DefectInfoMapper;
import com.deyuanyun.pic.pbf.mapper.PipeBodyDefectMapper;
import com.deyuanyun.pic.pbf.mapper.RepairTaskMapper;
import com.deyuanyun.pic.pipe.domain.CenterLine;
import com.deyuanyun.pic.pipe.domain.PipeSegmentInfo;
import com.deyuanyun.pic.pipe.service.PipeCenterLineService;
import com.deyuanyun.pic.settings.domain.pipe.PipeLine;
import com.deyuanyun.pic.settings.domain.pipe.PipeLineElement;
import com.deyuanyun.pic.settings.domain.pipe.PipeSegment;
import com.deyuanyun.pic.settings.domain.util.DomainFieldReflectUtil;
import com.deyuanyun.pic.settings.enumeration.UserState;
import com.deyuanyun.pic.settings.mapper.pipe.PipeLineElementMapper;
import com.deyuanyun.pic.settings.service.msgtemplate.PushMessage;
import com.deyuanyun.pic.settings.service.pipe.PipeLineService;
import com.deyuanyun.pic.settings.service.pipe.PipeSegmentService;
import com.deyuanyun.pic.settings.support.biz.CodeUtil;
import com.deyuanyun.pic.settings.task.StaticConsts;
import com.deyuanyun.pic.wf.domain.TaskInstance;
import com.deyuanyun.pic.wf.domain.TaskInstanceExample;
import com.deyuanyun.pic.wf.mapper.TaskInstanceMapper;
import com.deyuanyun.pic.wf.service.RepairWorkflowService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.util.*;

/**
 * @author Jerry
 * @Description
 * @date 2016-06-15
 */
@Service
public class PbfServiceImpl implements PbfService {
    //缺陷测量
    private static final String DEFECT_MEASURE = "1E3290704BF1749EE0530E0AA8C00060";

    //涂层维修修复方法
    private static final String CTRL_EXINSP_WAY = "XXXEEEFFFEEESSSFFFEEEWWWCCCRRR09";

    //申明待换管map
    private Map<String, Boolean> replacePipeTask = new LinkedHashMap<String, Boolean>();

    @Resource
    private PbfMapper pbfMapper;

    @Resource
    private PipeBodyDefectMapper pipeBodyDefectMapper;//非内检缺陷mapper

    @Resource
    private RepairWorkflowService repairWorkflowService;//换管或者更换维修方法mapper

    @Resource
    private ExinspOclpointMapper exinspOclpointMapper;//漏损点mapper

    @Resource
    private RecodeTaskMapper recodeTaskMapper;//漏损点维修任务mapper

    @Resource
    private DefectInfoMapper defectInfoMapper;//内检缺陷mapper

    @Resource
    private RepairTaskMapper repairTaskMapper;//维修任务Mapper

    @Autowired
    private PipeLineElementMapper pipeLineElementMapper;//管道中心线mapper

    @Resource
    private PipeLineService pipeLineService;//管道业务相关service

    @Resource
    private PipeSegmentService pipeSegmentService;//管段业务相关service

    @Resource
    private TaskInstanceMapper taskInstanceMapper;//taskInstance任务历史实例mapper

    @Resource
    private PipeCenterLineService pipeCenterLineService;//管道中心线service


    @Override
    public List<Map<String, Object>> testSelect() {
        return pbfMapper.testSelect();
    }

    @Override
    public PbfResult getUserName(String account) throws Exception {

        Map<String, Object> maps = new HashMap<String, Object>();
        PbfResult pbfResult = new PbfResult();
        List<Map<String, Object>> map = pbfMapper.login(account);

        if (map.size() == 0) {
            return setPorperty(PbfAppCode.USER_FAIL.getCode(),
                    PbfAppCode.USER_FAIL.getLabel(), pbfResult);
        }

        if (map.size() > 1) {
            return setPorperty(PbfAppCode.USER_REPEAT.getCode(),
                    PbfAppCode.USER_REPEAT.getLabel(), pbfResult);
        }

        Map<String, Object> map1 = map.get(0);
        if (!UserState.ACTIVATE.toString().equals(map1.get("STATE"))) {
            return setPorperty(PbfAppCode.USER_FORBIDDEN.getCode(),
                    PbfAppCode.USER_FORBIDDEN.getLabel(), pbfResult);
        }

        pbfResult.setCode(PbfAppCode.SUCCESS.getCode());
        pbfResult.setMsg(PbfAppCode.SUCCESS.getLabel());
        maps.put("UserName", map1.get("USERNAME"));
        pbfResult.setResult(maps);
        return pbfResult;
    }

    @Override
    public PbfResult login(String Param) throws Exception {
        JSONObject obj = JSON.parseObject(Param);
        int type = obj.getIntValue("Type");
        String account = obj.getString("Account").trim();
        String code = obj.getString("Code");
        PbfResult pbfResult = new PbfResult();
        Map<String, Object> map = new HashMap<String, Object>();
        List<Map<String, Object>> mapList = pbfMapper.login(account);

        if (account == null) {
            this.insertLog(Param, mapList, 1);
            return setPorperty(PbfAppCode.PARAMETER_FAIL.getCode(),
                    PbfAppCode.PARAMETER_FAIL.getLabel(), pbfResult);
        }

        if (type == 1) {//此为用户登录
            if (mapList == null) {
                this.insertLog(Param, mapList, 1);
                return setPorperty(PbfAppCode.USER_FAIL.getCode(),
                        PbfAppCode.USER_FAIL.getLabel(), pbfResult);
            }

            if (!code.equals(mapList.get(0).get("PWD"))) {
                this.insertLog(Param, mapList, 1);
                return setPorperty(PbfAppCode.CODE_FAIL.getCode(),
                        PbfAppCode.CODE_FAIL.getLabel(), pbfResult);
            }
            if (code != null && code.equals(mapList.get(0).get("PWD"))) {
                pbfResult.setCode(PbfAppCode.SUCCESS.getCode());
                pbfResult.setMsg(PbfAppCode.SUCCESS.getLabel());
                String userId = (String) mapList.get(0).get("ID_");
                Map<String, Object> realMap = pbfMapper.selectRealName(userId);
                if (realMap != null) {
                    String companyId = realMap.get("CPD").toString();
                    map.put("Corp", selectCompanyName(companyId));
                    map.put("PhoneNum", realMap.get("MOBILE"));
                    map.put("RealName", realMap.get("REALNAME"));
                }
                map.put("ID", userId);
                pbfResult.setResult(map);
                this.insertLog(Param, mapList, 0);
            }
            return pbfResult;
        } else {  //此为手机号登录

            if (StringUtils.isEmpty(code)) {
                return setPorperty(PbfAppCode.CAPTCHA_NULL.getCode(),
                        PbfAppCode.CAPTCHA_NULL.getLabel(), pbfResult);
            }
            String phone = account.trim();
            Asserts.assertTrue(StringUtils.isMobile(phone), "手机号码非法");
            Integer num = TempStoreDataSupport.pullData("ck_capt_" + phone);
            if (num == null) {
                num = 1;
            } else {
                ++num;
            }
            if (num > 5) {
                TempStoreDataSupport.removeData(StaticConsts.PM_LOGIN_CODE + phone);
                return setPorperty(PbfAppCode.CAPTCHA_FAILMORE.getCode(),
                        PbfAppCode.CAPTCHA_FAILMORE.getLabel(), pbfResult);
            }

            String ck = TempStoreDataSupport.pullData(StaticConsts.PM_LOGIN_CODE + phone);
            if (code.equals(ck)) {
                return setPorperty(PbfAppCode.CAPTCHA_SUCCESS.getCode(),
                        PbfAppCode.CAPTCHA_SUCCESS.getLabel(), pbfResult);
            } else {
                TempStoreDataSupport.pushDataByIdelTimeMinute("ck_capt_" + phone, num, StaticConsts.ck_capt_);
                return setPorperty(PbfAppCode.CAPTCHA_ERROR.getCode(),
                        PbfAppCode.CAPTCHA_ERROR.getLabel(), pbfResult);
            }
        }
    }


    /**
     * 通过递归查询一级公司名称
     *
     * @param companyId
     * @return
     */
    private String selectCompanyName(String companyId) {
        Map<String, Object> map = pbfMapper.selectCompanyName(companyId);
        Object parentId = map.get("PARENTID");
        String realName = map.get("SHORTNAME").toString();
        if (ObjectUtil.isNotNullEmpty(parentId)) {
            selectCompanyName(parentId.toString());
        } else {
            return realName;
        }
        return realName;
    }

    private PbfResult setPorperty(String code, String label, PbfResult pbfResult) {
        pbfResult.setCode(code);
        pbfResult.setMsg(label);
        return pbfResult;
    }

    @Override
    public void insertErrLog(PbfLoginLog pbfLoginLog) {
        pbfMapper.insertLog(pbfLoginLog);
    }

    @Override
    public Map<String, Object> findUserId(String userId) {
        Map<String, Object> map = pbfMapper.findUserId(userId);
        return map;
    }

    private void insertLog(String Param, List<Map<String, Object>> mapList, int type) {
        PbfLoginLog loginLog = JSON.parseObject(Param, PbfLoginLog.class);
        loginLog.setId(CommonUtil.getUUID());
        DomainInitUtil.initCreateDomain(loginLog);
        if (ObjectUtil.isNotNullEmpty(mapList)) {
            loginLog.setUserId((String) mapList.get(0).get("ID_"));
        }
        loginLog.setState(type);
        pbfMapper.insertLog(loginLog);
    }

    /**
     * 进行pagehelper
     *
     * @param param app传递参数
     */
    private void pageHelp(String param) {
        JSONObject obj = JSON.parseObject(param);
        int current = 1;
        if (null != obj.getInteger("PageNum")) {
            current = obj.getInteger("PageNum");
        }
        int pageCount = 20;
        if (null != obj.getInteger("PageSize")) {
            pageCount = obj.getInteger("PageSize");
        }
        PageHelper.startPage(current, pageCount);
    }

    @Override
    public Map<String, Object> getProjects(String param) throws Exception {
        pageHelp(param);
        Page<Map<String, Object>> result = pbfMapper.getProjects();
        List<Map<String, Object>> mapList = this.changeState(result, true);
        return addFenYe(mapList, result);

    }

    /**
     * 把List<Map<String,object>转化为map,并加上分页信息
     *
     * @param mapList 转换后的mapList(主要是转换维修状态和缺陷信息等字段）
     * @param result  从mapper底层取得page数据源
     * @return
     */
    private Map<String, Object> addFenYe(List<Map<String, Object>> mapList, Page<Map<String, Object>> result) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (mapList != null && mapList.size() > 0) {
            map.put("List", mapList);
        }
        map.put("PageSize", result.getPageSize());
        map.put("PageNum", result.getPageNum());
        map.put("Total", result.getTotal());
        return map;
    }

    @Override
    public Map<String, Object> findDefectList(String param) throws Exception {
        JSONObject obj = JSON.parseObject(param);
        String projectID = obj.getString("ProjectID");
        String userID = obj.getString("UserID");
        int pointType = obj.getInteger("PointType");
        if (projectID == null) {
            pageHelp(param);
            Page<Map<String, Object>> result = pbfMapper.findDefectListByUser(userID);//查询此用户的新增缺陷点
            List<Map<String, Object>> result1 = this.changeState(result, false);
            result1 = this.addRefPointAndImgToResult(result1, true);
            return addFenYe(result1, result);
        } else {
            pageHelp(param);
            Page<Map<String, Object>> result = null;
            List<Map<String, Object>> result1 = null;
            if (pointType == 1) {
                result = pbfMapper.findDefectListByTask(projectID);//查询此管体缺陷项目的所有缺陷点
                result = addXYZOnDefect(result);//对于管体缺陷项目的内检缺陷点加入xyz坐标
                result1 = this.changeState(result, true);
                result1 = this.addRefPointAndImgToResult(result1, false);//false指要传入参考点
            } else if (pointType == 2) {
                result = pbfMapper.findCtrlDefectListByTask(projectID);//查询此涂层维修项目的所有缺陷点
                result1 = this.changeState(result, true);
                result1 = this.addRefPointAndImgToResult(result1, true);//true指不用传参考点
            }
            return addFenYe(result1, result);
        }
    }

    /**
     * 加入xyz坐标
     *
     * @param result
     * @return
     */
    private Page<Map<String, Object>> addXYZOnDefect(Page<Map<String, Object>> result) {
        for (int i = 0; i < result.size(); i++) {
            Map<String, Object> map = result.get(i);
            if (ObjectUtil.isNotNullEmpty(map.get("XYZ"))) {
                String xyz = map.get("XYZ").toString();
                String[] xyzArray = xyz.split("#");
                if (ObjectUtil.isNotNullEmpty(xyzArray) && xyzArray.length == 3) {
                    map.put("X", xyzArray[0]);
                    map.put("Y", xyzArray[1]);
                    map.put("Z", xyzArray[2]);
                    map.remove("XYZ");
                }
            }
        }
        return result;
    }

    /**
     * 加入参考点和图片
     *
     * @param mapList
     * @param isPipeDefect
     * @return
     */
    private List<Map<String, Object>> addRefPointAndImgToResult(List<Map<String, Object>> mapList, Boolean isPipeDefect) {
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> map = mapList.get(i);
            // map.remove("PipeNameId");
            if (isPipeDefect) {//为非内检缺陷
                map.put("Pics", pbfMapper.findPipeDefectImgBydefectId(map.get("ID").toString()));
            } else {//内检缺陷
                if (map.get("PipeNameId") != null && map.get("Mile") != null) {
                    String pipeId = map.get("PipeNameId").toString();
                    BigDecimal mileage = new BigDecimal(map.get("Mile").toString());
                    List<Map<String, Object>> list = findRefPoint(pipeId, mileage);
                    if (ObjectUtil.isNotNullEmpty(list)) {
                        map.put("RefPoints", list);
                    }
                }
                map.put("Pics", pbfMapper.findDefectImgBydefectId(map.get("ID").toString()));
            }
        }

        return mapList;
    }

    /**
     * 加入参考点
     *
     * @param pipeId
     * @param mileage
     * @return
     */
    private List<Map<String, Object>> findRefPoint(String pipeId, BigDecimal mileage) {
        List<Map<String, Object>> refList = new ArrayList<Map<String, Object>>();
        // List<NearbyLocationDTO> refPontList = defectInfoService.queryNearbyLocationByMileage(pipeId,mileage);
        List<RefPointInfoDTO> refPontList = pbfMapper.findRefPontInfoBymileage(pipeId, mileage);
        if (refPontList.size() > 0) {
            for (RefPointInfoDTO nearBy : refPontList) {
                Map<String, Object> ref = new HashMap<String, Object>();
                ref.put("ID", nearBy.getId());
                ref.put("Name", nearBy.getTypeName());
                ref.put("Mile", nearBy.getMileage());
                ref.put("DownJoinClock", nearBy.getToCrossClock());
                ref.put("UpJoinClock", nearBy.getFromCrossClock());
                ref.put("RelativeMile", nearBy.getRelativeMileage());
                refList.add(ref);
            }
        }
        return refList;
    }

    /**
     * 转换对应key传至app
     *
     * @param result
     * @param isProject 是否是获取项目接口
     * @return
     */
    private List<Map<String, Object>> changeState(Page<Map<String, Object>> result, Boolean isProject) {
        for (int i = 0; i < result.size(); i++) {
            Map<String, Object> mapMarks = result.get(i);
            if (mapMarks.get("feaType") != null && mapMarks.get("subType") != null) {
                mapMarks.put("DefectTypeId", mapMarks.get("feaType") + "#" + mapMarks.get("subType"));
            } else if (mapMarks.get("feaType") != null && mapMarks.get("subType") == null) {
                mapMarks.put("DefectTypeId", mapMarks.get("feaType"));
            }
            if (!isProject) {
                if (RepairStateEnum.WAIT_FOR_REPAIR.toString().equals(mapMarks.get("Status").toString())) {
                    if (DefectStateEnum.state01.getCode().equals(mapMarks.get("dataState").toString())) {
                        mapMarks.put("Status", -1);//待审核
                    } else if (DefectStateEnum.state04.getCode().equals(mapMarks.get("dataState").toString())) {
                        mapMarks.put("Status", -2);//审核不通过
                    } else if (DefectStateEnum.state20.getCode().equals(mapMarks.get("dataState").toString())) {
                        mapMarks.put("Status", 1);
                    }
                } else if (RepairStateEnum.WAIT_FOR_REPLACE.toString().equals(mapMarks.get("Status").toString())) {
                    mapMarks.put("Status", 101);
                } else if (RepairStateEnum.DIFFICULT_TO_REPAIR.toString().equals(mapMarks.get("Status").toString())) {
                    mapMarks.put("Status", 100);
                } else {
                    mapMarks.put("Status", 3);//非内检缺陷没有修复中这个状态，所以只有修复完成这个状态；
                }
                mapMarks.remove("dataState");
            } else {
                if (RepairStateEnum.WAIT_FOR_REPAIR.toString().equals(mapMarks.get("Status").toString())) {
                    mapMarks.put("Status", 1);
                } else if (RepairStateEnum.MAINTENANCE.toString().equals(mapMarks.get("Status").toString())) {
                    mapMarks.put("Status", 2);
                }
            }
            mapMarks.remove("feaType");
            mapMarks.remove("subType");

        }
        return result;
    }


    @Override
    public void addorUpdatePipeBodyDefect(String Param) throws Exception {
        JSONObject obj = JSON.parseObject(Param);
        int type = obj.getIntValue("AddType");//判断是一键维修还是新增缺陷点还是需要审核的缺陷点
        String processId = obj.getString("ProcessID");
        String id = obj.getString("ID");//缺陷点ID
        String repairId = obj.getString("RepairWayId");
        if (type == 3) {//添加缺陷采集时新增的缺陷点（ps:此时相当于内检测数据，并没有数据提交这个状态）
            DefectResult result = JSON.parseObject(Param, DefectResult.class);
            //加此判断主要是因为防止调用webservie时间过长，而客户端重复提交同一个缺陷点造成主键冲突
            DefectInfo defectInfo = defectInfoMapper.selectByPrimaryKey(result.getId());
            if (defectInfo != null) {
                return;
            }
            String custom = result.getCustomNumber();
            if (StringUtils.isEmpty(custom)) {
                result.setCustomNumber(addRuleIfCustomIsNull(result));
            } else {
                result.setCustomNumber(checkingCustomUnique(custom, 1));
            }
            DomainInitUtil.initCreateDomain(result);
            result.setRepairState(RepairStateEnum.WAIT_FOR_REPAIR.toString());


            //计算绝对距离
            BigDecimal mileage = calculationMileage(obj);
            result.setMileage(mileage);

            pbfMapper.pipeDefect(result);
        } else if (type == 1) {//添加需审核的缺陷点
            AddDefectResult result = this.addData(Param);
            result.setDataStated(DefectStateEnum.state01.getCode());//已提交
            pbfMapper.pipeBodyDefect(result);
        } else if (type == 2) {//添加一键修复的缺陷点
            AddDefectResult result = this.addData(Param);
            result.setDataStated(DefectStateEnum.state20.getCode());//一键维修就注入审核已通过
            pbfMapper.pipeBodyDefect(result);
        }


        if (StringUtils.isNotEmpty(processId)) {//不为空说明此处为新增缺陷点采集


            Map<String, Object> maps = pbfMapper.selectTrenchRByDefId(id);//查询同沟关系表是否有这条数据
            if (ObjectUtil.isEmptyAll(maps)) {//为空才插入同沟关系表，表示一个缺陷点只有一次修复机会


                //对于新增加的缺陷点对于它的taskinstance保持和原始taskinstance保持一致
                List<Map<String, Object>> defectList = pbfMapper.findDefIdByprocessId(processId);
                String defectId = defectList.get(0).get("id").toString();

                pbfMapper.insertTrenchR(CommonUtil.getUUID(), id, processId); // 新增缺陷点是还要往同沟和缺陷关系表中插入对应数据


                TaskInstanceExample example = new TaskInstanceExample();
                example.createCriteria().andDefectInfoIdEqualTo(defectId)
                        .andDeletedEqualTo((short) 0);

                //之前的缺陷点的任务实例表
                List<TaskInstance> taskInstanceList = taskInstanceMapper.selectByExample(example);


                    for (int i = 0; i < taskInstanceList.size(); i++) {
                        TaskInstance taskInstance = taskInstanceList.get(i);
                        taskInstance.setId(CommonUtil.getUUID());
                        taskInstance.setCreateDate(new Date());//改变它的创建日期
                        taskInstance.setUpdateDate(null);
                        taskInstance.setUpdateRemark(null);
                        taskInstance.setDefectInfoId(id);
                        //对于内检流程新增缺陷点taskinstance表直接变成已完成
                        if(DEFECT_MEASURE.equals(taskInstance.getNodeId())){
                            taskInstance.setIsCompletion((short)1);
                        }
                        taskInstanceMapper.insertSelective(taskInstance);//插入taskinstance表
                    }

                DefectInfo defect = new DefectInfo();
                defect.setId(id);
                DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
                defect.setRepairState(RepairStateEnum.MAINTENANCE.toString());//对应状态（可为已完成，难以修复，待换管等）
                defectInfoMapper.updateByPrimaryKeySelective(defect);//更改内检缺陷点维修状态


                PostMeasureForm measureForm = postMeasureForm(Param,obj);

                BigDecimal actualDepth = obj.getBigDecimal("Depth");
                String[] defectTypeIds = obj.getString("DefectTypeId").split("#");
                String  defectTypeId = defectTypeIds[0];
                String defectTypeId1 = defectTypeIds[1];


                //计算峰值深度
                BigDecimal actualMaxdepth = calActualMaxdepth(id, actualDepth, defectTypeId);
                measureForm.setFeatureType(null);
                measureForm.setFeatureSubtype(null);
                measureForm.setActualFeaturetype(defectTypeId1);
                measureForm.setActualMaxdepth(actualMaxdepth);
                measureForm.setDefectInfoId(id);
                measureForm.setId(CommonUtil.getUUID());
                DomainInitUtil.initCreateDomain(measureForm);
                pbfMapper.insertMeasure(measureForm);

            }


        }

    }

    /**
     * 通过webservice 计算绝对距离
     *
     * @param obj
     * @return
     * @throws MalformedURLException
     */
    private BigDecimal calculationMileage(JSONObject obj) throws MalformedURLException {
        List list = new ArrayList();
        Map map = new HashMap();
        String pipeId = obj.getString("PipeNameId");//管道id

        CenterLine centerLine = pipeCenterLineService.getCenterLineByLineId(pipeId);
        if (centerLine != null) {
            map.put("id", centerLine.getGisId());
        }

        map.put("x", new BigDecimal(obj.getString("X")));
        map.put("y", new BigDecimal(obj.getString("Y")));
        list.add(map);
        String param = JSONArray.toJSONString(list);
        List<Double> mileage = UtilsServiceClient.getMileage(param);
        System.out.println("-------------------------" + mileage);
        if (mileage != null && mileage.size() > 0) {
            return BigDecimal.valueOf(mileage.get(0));
        } else {
            return null;
        }
    }

    /**
     * 验证custom_number是否唯一
     *
     * @param custom 用户输入的custom
     * @param type   类型 1是内检缺陷点 2是非内检
     * @return
     */
    private String checkingCustomUnique(String custom, int type) {
        List<DefectInfo> defectInfo = null;
        List<PipeBodyDefect> pipeDefect = null;
        if (1 == type) {
            DefectInfoExample example = new DefectInfoExample();
            example.createCriteria().andCustomNumberEqualTo(custom).andDeletedEqualTo((short) 0);
            defectInfo = defectInfoMapper.selectByExample(example);
        } else if (2 == type) {
            PipeBodyDefectExample example = new PipeBodyDefectExample();
            example.createCriteria().andCustomNumberEqualTo(custom).andDeletedEqualTo((short) 0);
            pipeDefect = pipeBodyDefectMapper.selectByExample(example);

        }
        if (ObjectUtil.isNotNullEmpty(defectInfo) || ObjectUtil.isNotNullEmpty(pipeDefect)) {
            Random ne = new Random();//实例化一个random的对象ne
            int x = ne.nextInt(9999 - 1000 + 1) + 1000;//为变量赋随机值1000-9999
            StringBuffer sb = new StringBuffer();
            sb.append(custom);
            sb.append(x);
            return sb.toString();
        }
        return custom;
    }

    @Override
    public PbfResult delPipeBodyDefect(String Param) {

        //TODO 此处要不要弄成逻辑删除
        JSONObject obj = JSON.parseObject(Param);
        String id = obj.getString("ID");
        pipeBodyDefectMapper.deleteByPrimaryKey(id);

        // TODO: 2016/10/27  此处应该有控制层来控制，待优化。
        PbfResult pbfResult = new PbfResult();
        pbfResult.setCode(PbfAppCode.SUCCESS.getCode());
        pbfResult.setMsg(PbfAppCode.SUCCESS.getLabel());

        return pbfResult;
    }

    /**
     * app端不输入缺陷点编号时后台生成编号规则
     *
     * @param obj
     * @return
     * @throws Exception
     */
    private String addRuleIfCustomIsNull(Object obj) throws Exception {
        String pipeLineId = null;
        String defectType = null;
        if (obj instanceof AddDefectResult) {
            AddDefectResult result = (AddDefectResult) obj;
            pipeLineId = result.getPipeLineId();
            defectType = result.getDefectType();
        } else if (obj instanceof DefectResult) {
            DefectResult result = (DefectResult) obj;
            pipeLineId = result.getPipeLineId();
            defectType = result.getFeatureType();
        }
        PipeLine line = pipeLineService.selectByPrimaryKey(pipeLineId);
        StringBuffer sb = new StringBuffer();
        sb.append(line.getAbridge());
        DefectTypeCode defectTypeCode = DefectTypeCode.getVal(defectType);
        switch (defectTypeCode) {
            case ML:
                sb.append("ML");
                break;
            case DENT:
                sb.append("DENT");
                break;
            case WAN:
                sb.append("WAN");
                break;
            case OVAL:
                sb.append("OVAL");
                break;
            case CRAC:
                sb.append("CRAC");
                break;
            case OTHE:
                sb.append("OTHE");
                break;
        }
        sb.append(DateUtil.DateToStringYMd(new Date()));
        Random ne = new Random();//实例化一个random的对象ne
        int x = ne.nextInt(9999 - 1000 + 1) + 1000;//为变量赋随机值1000-9999
        sb.append(x);
        return sb.toString();
    }

    /**
     * 对非内检缺陷点进行业务数据注入
     *
     * @param Param app传过来的参数
     * @return
     */
    private AddDefectResult addData(String Param) throws Exception {
        AddDefectResult result = JSON.parseObject(Param, AddDefectResult.class);
        PipeBodyDefect defectInfo = pipeBodyDefectMapper.selectByPrimaryKey(result.getId());
        String customNumber = result.getCustomNumber();
        if (StringUtils.isEmpty(customNumber)) {
            result.setCustomNumber(addRuleIfCustomIsNull(result));
        } else {
            if (ObjectUtil.isEmptyAll(defectInfo) || !defectInfo.getCustomNumber().equals(result.getCustomNumber())) {
                String custom = result.getCustomNumber();
                result.setCustomNumber(checkingCustomUnique(custom, 2));
            }
        }

        DomainInitUtil.initCreateDomain(result);
        result.setApparatusType((short) 1);//移动端插入缺陷数据
        result.setRepairState(RepairStateEnum.WAIT_FOR_REPAIR.toString());
        return result;
    }

    @Override
    public Map<String, Object> getConfigs() throws Exception {
        Map<String, Object> newMap = new HashMap<String, Object>();
        Map<String, Object> map1 = new HashMap<String, Object>();
        Map<String, Object> map2 = new HashMap<String, Object>();
        Map<String, Object> map3 = new HashMap<String, Object>();

        //根系植物
        newMap.put("Plants", CodeUtil.getAppCodeList(ConfigCode.TDF_DEEP_ROOTED_PLANT.getCode()));
        //土壤松紧度
        newMap.put("SoilCompact", CodeUtil.getAppCodeList(ConfigCode.TDF_SOIL_COMPACTNESS.getCode()));
        //土壤干湿度
        newMap.put("SoilHumidity", CodeUtil.getAppCodeList(ConfigCode.TDF_SOIL_HUMIDITY.getCode()));
        //土壤颗粒
        newMap.put("SoilParticles", CodeUtil.getAppCodeList(ConfigCode.TDF_SOIL_PARTICLES_GROUP.getCode()));
        //防腐层材料
        newMap.put("CoatingMaterial", CodeUtil.getAppCodeList(ConfigCode.COATINGMATERIAL.getCode()));
        //外观质量
        newMap.put("Appearance", CodeUtil.getAppCodeList(ConfigCode.TDF_APPEARANCE.getCode()));
        //防锈等级
        newMap.put("DerustGrade", CodeUtil.getAppCodeList(ConfigCode.TDF_DERUSTING_GRADE.getCode()));
        //缺陷类型（由于此类型有1 2级，故不用codeutil方法）
        newMap.put("Defect", transformObj(ConfigCode.TDF_FEATURE_TYPE.getCode(), map1, false));
        //复合材料补强修复方法
        newMap.put("CompMaterialRepairWay", CodeUtil.getAppCodeList(ConfigCode.TDF_COMPOSITES_REPAIR_METHOD.getCode()));
        //复合材料补强修复材料
        newMap.put("CompMaterialRepairMaterial", CodeUtil.getAppCodeList(ConfigCode.TDF_COMPOSITES_REPAIR_MATERIAL.getCode()));
        //钢质环氧套筒补强修复套筒结构
        newMap.put("SteelEpoxySleeveStructure", CodeUtil.getAppCodeList(ConfigCode.TDF_SOCKET_STRUCTURE.getCode()));
        //材质(包含钢质环氧套筒补强修复和A/B型套筒和换管）
        newMap.put("PipeMaterial", transformObj(ConfigCode.MATERIAL.getCode(), map3, false));
        //防腐修复材料（防腐层修复和换管）
        newMap.put("CoatingRepairMaterial", CodeUtil.getAppCodeList(ConfigCode.TDF_REPAIR_MATERIAL.getCode()));
        //制管方式（换管）
        newMap.put("PipeManufacture", CodeUtil.getAppCodeList(ConfigCode.MANUPIPE_TYPE.getCode()));
        //管径（换管）
        newMap.put("PipeDiameter", CodeUtil.getAppCodeList(ConfigCode.DIAMETER.getCode()));
        //防腐等级（换管)
        newMap.put("CoatingGrade", CodeUtil.getAppCodeList(ConfigCode.COATING_GRADE.getCode()));
        //无损检测类型
        newMap.put("NDTType", CodeUtil.getAppCodeList(ConfigCode.NDT_TYPE.getCode()));
        //地下水情况
        newMap.put("GroundWater", CodeUtil.getAppCodeList(ConfigCode.TDF_GROUNDWATER.getCode()));
        //修复方法配置
        newMap.put("Repair", transformObj(null, map2, true));
        //补口
        newMap.put("Join", CodeUtil.getAppCodeList(ConfigCode.TDF_IS_JOINT.getCode()));
        //灌注工艺
        newMap.put("PerfusionProcess", CodeUtil.getAppCodeList(ConfigCode.PERFUSION_PROCESS.getCode()));
        //缺陷来源
        newMap.put("DefectDerive", CodeUtil.getAppCodeList(ConfigCode.TDF_DEFECT_RESOURCE.getCode()));
        //管道管段配置
        newMap.put("Pipe", getPipeSegment());

        return newMap;
    }

    /**
     * 封装获取管道管段配置配置，传统做法是前台点击下拉框发球请求获取所有管段，用户再点击对应的管道发送请求
     * 到后台获取对应的管段，而此做法一次请求获取全部的管段管段并当成配置信息来处理，并严格按照json参数格式
     * 书写，大小写敏感。对于出现的双重for循环，由于管道的条数不多，而且对此方法和获取管道以及获取管段的方法
     * 加入缓存，故程序在初次执行的话会访问数据库性能可能会稍微影响，但之后影响极小。
     * ps(暂时没有想到其他更好的方法，如果有其他更好的方法，欢迎吐槽）
     *
     * @return
     */
    private Map<String, Object> getPipeSegment() {
        List<Map<String, Object>> mapList = new ArrayList();
        List<PipeLine> listPipe = pipeLineService.getLine();
        // List<Map> mapPipe = BeanConverter.toListMap(listPipe);

        for (PipeLine pipeLine : listPipe) {
            Map<String, Object> map = new HashMap<String, Object>();
            List<Map<String, Object>> mapList1 = new ArrayList();
            map.put("ID", pipeLine.getId());
            map.put("Name", pipeLine.getShowName());
            List<PipeSegment> segmentList = pipeSegmentService.getSegmentByLineId(pipeLine.getId());
            for (PipeSegment pipeSegment : segmentList) {

                Map<String, Object> map1 = new HashMap<String, Object>();
                map1.put("ID", pipeSegment.getId());
                map1.put("Name", pipeSegment.getName());
                mapList1.add(map1);
            }
            if (ObjectUtil.isNotNullEmpty(mapList1)) {
                map.put("List", mapList1);
            }
            mapList.add(map);
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("List", mapList);
        return map;
    }

    /**
     * 转化数据分层2级
     * "List": [
     * {
     * "ID": "1E3290704BF1749EE0530E0AA8C01412",
     * "List": [
     * {
     * "ID": "1E3290704BF1749EE0530E0AA8C01401",
     * "Name": "Q195"
     * }],
     * "Name": "L175Ⅰ类(A25Ⅰ类)"
     * }]
     *
     * @param code 编码表major_code值
     * @param map  把单个配置信息存入的对象(map)
     * @return
     */
    private Map<String, Object> transformObj(String code, Map<String, Object> map, boolean isRepair) {
        List<Map<String, Object>> mapList = null;
        if (isRepair) {
            //修复方法配置时 code为空
            mapList = pbfMapper.getRepair();
            for (int i = 0; i < mapList.size(); i++) {
                Map<String, Object> mapMark = mapList.get(i);
                List<Map<String, Object>> mapResult = pbfMapper.getRepairNode((String) mapMark.get("ID"));
                mapMark.put("Nodes", mapResult);
                if ("0".equals(mapMark.get("sus").toString())) {
                    mapMark.put("Obsolete", false);
                    mapMark.remove("sus");
                } else {
                    mapMark.put("Obsolete", true);
                    mapMark.remove("sus");
                }
            }
        } else {
            mapList = pbfMapper.getFearture(code);
            for (int i = 0; i < mapList.size(); i++) {
                Map<String, Object> mapMark = mapList.get(i);
                List<Map<String, Object>> mapResult = pbfMapper.getFeartureBypd(mapMark.get("ID").toString());
                //如果缺陷类型二级菜单没有，则不需要传值
                if (ObjectUtil.isNotNullEmpty(mapResult)) {
                    mapMark.put("List", mapResult);
                }
            }
        }
        map.put("List", mapList);
        return map;
    }

    /**
     * @param a 缺陷点数组
     * @param b 维修状态
     * @param c 同沟Id
     */
    private void doSomeThing(JSONArray a, String b, String c, int type) {
        for (int i = 0; i < a.size(); i++) {
            Map<String, Object> maps = pbfMapper.selectTrenchRByDefId(a.get(i).toString());//查询同沟关系表是否有这条数据
            if (ObjectUtil.isEmptyAll(maps)) {//为空才插入同沟关系表，表示一个缺陷点只有一次修复机会

                pbfMapper.insertTrenchR(CommonUtil.getUUID(), a.get(i).toString(), c);//插入缺陷与同沟关系表


                if (2 == type) {
                    repairWorkflowService.createOrUpdateTaskInstance(CTRL_EXINSP_WAY, a.get(i).toString());//插入task_instance表

                    ExinspOclpoint exinspOclpoint = new ExinspOclpoint();
                    exinspOclpoint.setId(a.get(i).toString());
                    DomainInitUtil.initUpdateDomain(exinspOclpoint, "更改维修状态");
                    exinspOclpoint.setRepairState(b);
                    exinspOclpointMapper.updateByPrimaryKeySelective(exinspOclpoint);//更改漏损点维修状态

                } else {
                    // TODO: 2016/7/6 jerry这里维修点ID其实可以采用app传过来，而不用去查数据库。
                    Map<String, Object> map = pbfMapper.findRepairIdBydefId(a.get(i).toString());
                    if (ObjectUtil.isNotNullEmpty(map)) {
                        if (ObjectUtil.isNotNullEmpty(map.get("repairId"))) {
                            String repairId = map.get("repairId").toString();//维修方法Id
                            repairWorkflowService.createOrUpdateTaskInstance(repairId, a.get(i).toString());//插入task_instance表
                        }
                    }
                    DefectInfo defect = new DefectInfo();
                    defect.setId(a.get(i).toString());
                    DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
                    defect.setRepairState(b);
                    defectInfoMapper.updateByPrimaryKeySelective(defect);//更改内检缺陷点维修状态
                }

            }

        }
    }

    @Override
    @PushMessage("#Param")
    public void postForm(String Param) throws Exception {
        JSONObject obj = JSON.parseObject(Param);
        JSONArray DefectIds = obj.getJSONArray("DefectIds");
        String nodeId = obj.getString("Type");
        FormCode formCode = FormCode.getVal(nodeId);
        String projectId = obj.getString("ProjectID");
        String processId = obj.getString("ProcessID"); //当进程为管沟开挖时定义一个processId;
        String id = obj.getString("ID");//流程表单id
        int pointType = obj.getInteger("PointType");//判断是否是漏损点还是缺陷点
        boolean changePipe;//是否需要换管
        switch (formCode) {
            // TODO: 2016/11/25 听说涂层维修项目的缺陷点在管沟开挖时要注入PIC_CTRL_EXINSP_OCLPOINT_DIG表
            // TODO 但是在这个管沟开挖这个表单有没有完全对应这个表的字段，意思就是说在接下来的流程有
            //TODO 对应这个表的剩余字段，按照设计来说应该是一张表对应一个表单，这里我觉得很奇怪。
            //TODO 暂时未对PIC_CTRL_EXINSP_OCLPOINT_DIG这个表进行注入
            case TRENCH_EXCAVATION://管道开挖
                TrenchMark trench = new TrenchMark();
                DomainInitUtil.initCreateDomain(trench); //插入同沟表
                trench.setCreateUser(obj.getString("UserID"));
                trench.setId(processId);
                pbfMapper.insertTrench(trench);


                PostDig postDig = JSON.parseObject(Param, PostDig.class);
                Boolean unRepairable = obj.getBoolean("UnRepairable");
                if (unRepairable) {//true 难以维修 更换维修状态 以及创建taskinstance
                    List<Map<String, Object>> newMap = null;
                    if (1 == pointType) {
                        newMap = pbfMapper.findDefectList(projectId);
                    } else if (2 == pointType) {
                        newMap = pbfMapper.findCtrlDefectListByTask(projectId);
                    }
                    if (ObjectUtil.isNotNullEmpty(newMap)) {
                        if (DefectIds.size() == newMap.size()) {
                            changeRepairTaskState(obj, RepairStateEnum.ALREADY_REPAIR.toString(), pointType);//难以维修更改repair-task表的维修状态
                        } else {
                            changeState(obj, pointType);//难以维修更改repair-task表的维修状态
                        }
                    }
                    doSomeThing(DefectIds, RepairStateEnum.DIFFICULT_TO_REPAIR.toString(), processId, pointType);
                    postDig.setIsDifficultToRepair((short) 1);
                } else {
                    doSomeThing(DefectIds, RepairStateEnum.MAINTENANCE.toString(), processId, pointType);
                    changeRepairTaskState(obj, RepairStateEnum.MAINTENANCE.toString(), pointType);//走正常流程更改repair-task表的维修状态
                    postDig.setIsDifficultToRepair((short) 0);
                }
                DomainInitUtil.initCreateDomain(postDig);//插入管沟开挖记录表
                pbfMapper.insertTrenchExcavtion(postDig);

                updateTaskInstanceStatus(processId, nodeId, false);//更改task-instance状态

                //直接将sort置为最大，以至于将难以维修的缺陷点除了管沟开挖其他的全部置为跳过
                if (unRepairable) {
                    for (int i = 0; i < DefectIds.size(); i++) {
                        TaskInstance taskInstance = new TaskInstance();
                        DomainInitUtil.initUpdateDomain(taskInstance, "跳过相关节点");
                        taskInstance.setIsCompletion((short) 0);
                        taskInstance.setDefectInfoId(DefectIds.get(i).toString());
                        taskInstance.setJumpNode((short) 1);
                        taskInstance.setSort((short) 9);
                        pbfMapper.updateTaskInstanceJump(taskInstance);
                    }
                }
                break;

            case CORROSION_ENVIRONMENT: //腐蚀环境调查
                PostCorrosionEnvSurvey postCorrosion = JSON.parseObject(Param, PostCorrosionEnvSurvey.class);
                DomainInitUtil.initCreateDomain(postCorrosion);
                pbfMapper.insertCorrosionEnvironment(postCorrosion);

                updateTaskInstanceStatus(processId, nodeId, false);
                break;

            case COAT_SURVEY://防腐层调查
                PostCoatingSurvey postCoating = JSON.parseObject(Param, PostCoatingSurvey.class);
                DomainInitUtil.initCreateDomain(postCoating);
                pbfMapper.insertCoatSurvey(postCoating);

                changePipe = obj.getBoolean("ChangePipe");//是否需要换管
                if (changePipe) {
//                    updateDefectRepairState(DefectIds, RepairStateEnum.WAIT_FOR_REPLACE.toString());//修改成待换管状态
                    replacePipeTask.put(processId, true);
                }
                updateTaskInstanceStatus(processId, nodeId, changePipe);

                break;

            case SURFACE_TREATMENT: //表面处理
                PostSurfaceDeal postSurfaceDeal = JSON.parseObject(Param, PostSurfaceDeal.class);
                DomainInitUtil.initCreateDomain(postSurfaceDeal);
                pbfMapper.insertSurfaceTreatment(postSurfaceDeal);

                changePipe = obj.getBoolean("ChangePipe");//是否需要换管
                if (changePipe) {
//                    updateDefectRepairState(DefectIds, RepairStateEnum.WAIT_FOR_REPLACE.toString());//修改成待换管状态
                    replacePipeTask.put(processId, true);
                }
                updateTaskInstanceStatus(processId, nodeId, changePipe);
                break;

            case CP_SURVEY:  //阴保调查
                PostCathodicProtectionSurvey survey = JSON.parseObject(Param, PostCathodicProtectionSurvey.class);
                DomainInitUtil.initCreateDomain(survey);
                pbfMapper.insertCPSurvey(survey);

                updateTaskInstanceStatus(processId, nodeId, false);
                break;

            case CTRL_EXINSP: //漏损点测量
                RepairLeakageDto leakage = JSON.parseObject(Param, RepairLeakageDto.class);
                DomainInitUtil.initCreateDomain(leakage);
                pbfMapper.insertLeakagePoint(leakage);

                updateTaskInstanceStatus(processId, nodeId, false);
                break;

            case DEFECT_MEASURE:  //缺陷测量
                PostMeasureForm measureForm = postMeasureForm(Param,obj);

                String defectId = obj.getString("DefectId");
                String oldRepairWayId = obj.getString("RepairWayId");
                String newRepairWayId = obj.getString("NewRepairWayId");
                String repairReason = obj.getString("Remark");
                String workLoad = obj.getString("WorkLoad");
                BigDecimal actualDepth = obj.getBigDecimal("Depth");
                String defectTypeId = obj.getString("NewDefectTypeId");

                //计算峰值深度
                BigDecimal actualMaxdepth = calActualMaxdepth(defectId, actualDepth, defectTypeId);

                measureForm.setActualMaxdepth(actualMaxdepth);
                DomainInitUtil.initCreateDomain(measureForm);
                pbfMapper.insertMeasure(measureForm);


                changePipe = obj.getBoolean("ChangePipe");//是否需要换管
                if (changePipe) {//选择了换管
//                    updateDefectRepairStateByProcessId(processId, RepairStateEnum.WAIT_FOR_REPLACE.toString());//修改成待换管状态
                    updateTaskInstanceStatusByDefectId(defectId,nodeId,changePipe);
                    replacePipeTask.put(processId, true);
                } else {//没有选择换管
                    updateTaskInstanceStatusByDefectId(defectId,nodeId,changePipe);
                }


                List<Map<String, Object>> defList = pbfMapper.selectDefectIdBytrenchId(processId);
                if (!oldRepairWayId.equals(newRepairWayId)) { //如果缺陷点原始修复方法和变更方法不一样才进行换节点操作。
                    for (int i = 0; i < defList.size(); i++) {
                        Map<String, Object> mapMark = defList.get(i);
                        String defId = mapMark.get("defectId").toString();
                        createOrUpdateTaskInstance(obj, defId);
                    }
                }

                //根据实际情况更改内检测缺陷点的修复方法
                DefectInfo def = new DefectInfo();
                def.setId(defectId);
                def.setRepairType(newRepairWayId);
                def.setRepairRemark(repairReason);
                def.setRepairWorkload(workLoad);
                defectInfoMapper.updateByPrimaryKeySelective(def);

                break;

            case REPAIR_COMPOSITES://复合材料补强修复
                PostCompMaterialRepair materialRepair = JSON.parseObject(Param, PostCompMaterialRepair.class);
                DomainInitUtil.initCreateDomain(materialRepair);
                pbfMapper.insertCompMaterial(materialRepair);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }


                break;

            case REPAIR_EPOXY_SLEEVE://钢质环氧套筒补强修复
                PostSteelEpoxySleeve steelEpoxy = JSON.parseObject(Param, PostSteelEpoxySleeve.class);
                DomainInitUtil.initCreateDomain(steelEpoxy);
                pbfMapper.insertSteelEpoxy(steelEpoxy);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }


                break;

            case REPAIR_ATYPE_SLEEVE://A型套筒补强修复
                PostABSleeveForm ABSleeve = JSON.parseObject(Param, PostABSleeveForm.class);
                DomainInitUtil.initCreateDomain(ABSleeve);
                pbfMapper.insertABSleeve(ABSleeve);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }


                break;

            case REPAIR_BTYPE_SLEEVE: //B型套筒补强修复
                PostABSleeveForm BSleeve = JSON.parseObject(Param, PostABSleeveForm.class);
                DomainInitUtil.initCreateDomain(BSleeve);
                pbfMapper.insertABSleeve(BSleeve);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }
                break;

            case REPAIR_REPLACE_PIPE:   //换管
                PostChangePipe change = JSON.parseObject(Param, PostChangePipe.class);
                DomainInitUtil.initCreateDomain(change);
                pbfMapper.insertChangePipe(change);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.MAINTENANCE.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {

                    updateTaskInstanceStatus(processId, nodeId, false);
                }

                break;

            case COAT_REPAIR: //防腐层修复
                CoatingRepairDto coatingRepairDto = JSON.parseObject(Param, CoatingRepairDto.class);
                DomainInitUtil.initCreateDomain(coatingRepairDto);
                pbfMapper.insertCoatRepair(coatingRepairDto);
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());

                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }


                break;

            case TRENCH_BACKFILL: //管沟回填
                TrenchBackPillDto trenchBackPillDto = JSON.parseObject(Param, TrenchBackPillDto.class);
                DomainInitUtil.initCreateDomain(trenchBackPillDto);
                pbfMapper.insertTrenchBackPill(trenchBackPillDto);

                List<Map<String, Object>> mapList = pbfMapper.findDefIdByprocessId(processId);

                for (int i = 0; i < mapList.size(); i++) {
                    String id1 = mapList.get(i).get("id").toString();
                    if (2 == pointType) {
                        ExinspOclpoint exinspOclpoint = exinspOclpointMapper.selectByPrimaryKey(id1);
                        exinspOclpoint.setId(exinspOclpoint.getId());
                        DomainInitUtil.initUpdateDomain(exinspOclpoint, "更改维修状态");
                        exinspOclpoint.setRepairState(RepairStateEnum.ALREADY_REPAIR.toString());
                        exinspOclpointMapper.updateByPrimaryKeySelective(exinspOclpoint);//更改漏损点维修状态
                    } else {
                        DefectInfo defectInfo = defectInfoMapper.selectByPrimaryKey(id1);
//                        if (!RepairStateEnum.WAIT_FOR_REPLACE.toString().equals(defectInfo.getRepairState())) {
//                            //不是待换管才走以下修改状态，把它修改成已完成
//                            updateDefectRepairState(id1, RepairStateEnum.ALREADY_REPAIR.toString());
//                        }
                        if (replacePipeTask.containsKey(processId)) {
                            updateDefectRepairState(id1, RepairStateEnum.WAIT_FOR_REPLACE.toString());
                        } else {
                            updateDefectRepairState(id1, RepairStateEnum.ALREADY_REPAIR.toString());
                        }
                    }


                }


                updateTaskInstanceStatus(processId, nodeId, false);

                changeState(obj, pointType);
                break;

            case REPAIR_OTHER://其他修复方法
                RepairOtherDto other = JSON.parseObject(Param, RepairOtherDto.class);
                DomainInitUtil.initCreateDomain(other);
                pbfMapper.insertRepairOther(other);


                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());
                    insertDefectRepairMethod(DefectIds, id, nodeId);
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }


                break;

            case WELD_REPAIR://焊接
                PostPipeWelding pipeWelding = JSON.parseObject(Param, PostPipeWelding.class);//insert 换管焊缝表
                DomainInitUtil.initCreateDomain(pipeWelding);
                pbfMapper.insertPostWelding(pipeWelding);

                List<PostWeld> postWeldList = pipeWelding.getPostWelds();
                for (int i = 0; i < postWeldList.size(); i++) {//insert焊缝信息表
                    postWeldList.get(i).setRepairPipeWeldingId(id);
                    DomainInitUtil.initCreateDomain(postWeldList.get(i));
                    postWeldList.get(i).setId(CommonUtil.getUUID());
                    pbfMapper.insertPostWeld(postWeldList.get(i));
                }
                if (projectId == null) {//项目Id为空，说明此时走的是  <新增缺陷 -审核通过 -对应流程>
                    changePipeBodyRepairState(DefectIds, RepairStateEnum.ALREADY_REPAIR.toString());
                } else {
                    updateTaskInstanceStatus(processId, nodeId, false);
                }

                break;
        }

    }

    /**
     * 在postform方法中的缺陷测量和内检流程中新加缺陷点都要用到这个方法
     * @param Param
     * @param obj
     */
    private PostMeasureForm postMeasureForm(String Param,JSONObject obj){
        PostMeasureForm measureForm = JSON.parseObject(Param, PostMeasureForm.class);
        JSONArray ndtCodes = obj.getJSONArray("NDTCodes");
        if (ndtCodes != null && ndtCodes.size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < ndtCodes.size(); i++) {
                if(ndtCodes.get(i) != null){
                    String ndtcode = ndtCodes.get(i).toString();
                    sb.append(ndtcode);
                    sb.append(",");
                }
            }
            sb.deleteCharAt(sb.length() - 1);
            measureForm.setNdtReportNumber(sb.toString());
        }
        return measureForm;
    }


    /**
     * 通过app页面提交深来计算峰值深度
     * 凹陷：峰值深度=深度/管径
     * 其他缺陷:峰值深度=深度/壁厚
     *
     * @param defectInfoId 缺陷点id
     * @param actualDepth  app提交深度
     * @param feautureType app实测缺陷类型
     * @return
     */
    private BigDecimal calActualMaxdepth(String defectInfoId,
                                         BigDecimal actualDepth, String feautureType) {
        BigDecimal actualMaxdepth = null;//申明要返回的值
        //通过二级id找到父id
        String[] fType = feautureType.split("#");
        String fid = null;
        if (fType != null && fType.length > 1) {
            fid = fType[0];
        }
        DefectTypeCode defectType = DefectTypeCode.getVal(fid);
        //通过defectInfoId找到这个内检缺陷点对应的管道id
        DefectInfo defectInfo = defectInfoMapper.selectByPrimaryKey(defectInfoId);
        String pipeId = defectInfo.getPipeLineId();
        final BigDecimal mileage = defectInfo.getMileage();

        List<PipeLineElement> pleList = pipeLineElementMapper.queryElementsById(pipeId, "0");
        Collection<PipeLineElement> result = Collections2.filter(pleList, new Predicate<PipeLineElement>() {
            @Override
            public boolean apply(PipeLineElement lineElement) {
                    if (mileage != null && 1 == (mileage.compareTo(lineElement.getMileage()))) {
                        return false;
                    }
                return true;
            }
        });
        List<PipeLineElement> list = new ArrayList<PipeLineElement>(result);
        String elementId = list.get(0).getElementId();
        //得到比mileage大的PipeLineElement集合，取第一个即可
        PipeSegmentInfo pipeSegmentInfo = null;
        List<PipeSegmentInfo> segmentInfo = pbfMapper.selectPipeSegmentInfo(pipeId, elementId);
        if (segmentInfo != null && segmentInfo.size() > 0) {
            pipeSegmentInfo = segmentInfo.get(0);
        } else {
            return null;
        }
        BigDecimal wallthickness = pipeSegmentInfo.getWallthickness();
        String diameter = CodeUtil.getName(pipeSegmentInfo.getDiameter());//管径
        BigDecimal bigdiameter = new BigDecimal(diameter);

        if(actualDepth == null || bigdiameter == null || wallthickness == null
                || bigdiameter == new BigDecimal(0)
                || wallthickness == new BigDecimal(0)){
            return  null;
        }

        if (DefectTypeCode.DENT.equals(defectType)) {
            actualMaxdepth = actualDepth.divide(bigdiameter, 2, BigDecimal.ROUND_HALF_UP);
        } else if (DefectTypeCode.ML.equals(defectType) || DefectTypeCode.CRAC.equals(defectType)
                || DefectTypeCode.OTHE.equals(defectType)) {
            actualMaxdepth = actualDepth.divide(wallthickness, 2, BigDecimal.ROUND_HALF_UP);
        }
        return actualMaxdepth;
    }

    /**
     * 根据同沟id更改内检缺陷点的维修状态
     *
     * @param processId
     * @param repairState
     */
    private void updateDefectRepairStateByProcessId(String processId, String repairState) {
        List<Map<String, Object>> mapList = pbfMapper.selectDefectIdBytrenchId(processId);
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> mapMark = mapList.get(i);
            String defectId = mapMark.get("defectId").toString();
            DefectInfo defect = new DefectInfo();
            defect.setId(defectId);
            DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
            defect.setRepairState(repairState);//对应状态（可为已完成，难以修复，待换管等）
            defectInfoMapper.updateByPrimaryKeySelective(defect);//更改内检缺陷点维修状态

        }
    }

    /**
     * 更改内检缺陷点表的reparir_state状态
     *
     * @param ids         内检缺陷ids
     * @param repairState 具体状态值
     */
    private void updateDefectRepairState(Object ids, String repairState) {
        if (ids instanceof String) {
            DefectInfo defect = new DefectInfo();
            defect.setId((String) ids);
            DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
            defect.setRepairState(repairState);//对应状态（可为已完成，难以修复，待换管等）
            defectInfoMapper.updateByPrimaryKeySelective(defect);//更改内检缺陷点维修状态
        } else if (ids instanceof JSONArray) {
            JSONArray ids1 = (JSONArray) ids;
            for (int i = 0; i < ids1.size(); i++) {
                DefectInfo defect = new DefectInfo();
                String id = ids1.get(i).toString();
                defect.setId(id);
                DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
                defect.setRepairState(repairState);//对应状态（可为已完成，难以修复，待换管等）
                defectInfoMapper.updateByPrimaryKeySelective(defect);//更改内检缺陷点维修状态
            }
        }

    }

    @Cacheable(value = "tempStoreData")
    @Override
    public String findTabNameByNodeId(String id) {
        String tabName = pbfMapper.findTabNameByNodeId(id);
        return tabName;
    }

    /**
     * 此方法用处2点
     * 1.如果在管道开挖是缺陷点是难以维修那么修改对应任务状态
     * 2.内检缺陷点修复完成也就是走管沟回填是判断对应任务状态
     *
     * @param obj 前台APP传递参数
     */
    private void changeState(JSONObject obj, int type) {
        String projectId = obj.getString("ProjectID");
        List<Map<String, Object>> repairStateList = null;
        if (1 == type) {
            repairStateList = pbfMapper.getRepairStateByTaskId(projectId);//projectId为维修任务Id
        } else if (2 == type) {
            repairStateList = pbfMapper.getCrtlRepairStateByTaskId(projectId);//projectId为涂层任务Id
        }

        changeRepairTaskState(obj, RepairStateEnum.ALREADY_REPAIR.toString(), type);//已完成
        for (int i = 0; i < repairStateList.size(); i++) {
            Map<String, Object> map = repairStateList.get(i);
            String repState = ObjectUtil.isNotNullEmpty(map.get("repState")) ? map.get("repState").toString() : null;
            if (RepairStateEnum.MAINTENANCE.toString().equals(repState) ||
                    RepairStateEnum.WAIT_FOR_REPAIR.toString().equals(repState)) {
                changeRepairTaskState(obj, RepairStateEnum.MAINTENANCE.toString(), type);//修复中
                break;
            }
        }
    }

    /**
     * 换管或者更换维修方法
     *
     * @param obj jsonObject
     * @param obt jsonArray(主要是缺陷点数组)
     */
    private void createOrUpdateTaskInstance(JSONObject obj, Object obt) {
        String repairId = obj.getString("NewRepairWayId");//得到换管流程Id
        if (obt instanceof JSONArray) {
            for (int i = 0; i < ((JSONArray) obt).size(); i++) {
                repairWorkflowService.createOrUpdateTaskInstance(repairId, (String) ((JSONArray) obt).get(i));
            }
        } else if (obt instanceof String) {
            repairWorkflowService.createOrUpdateTaskInstance(repairId, (String) obt);
        }

    }

    /**
     * 更改RepairTask表的维修状态
     *
     * @param obj
     * @param repairState
     */
    private void changeRepairTaskState(JSONObject obj, String repairState, int type) {
        if (1 == type) {
            RepairTask record = new RepairTask();
            DomainInitUtil.initUpdateDomain(record, "更换维修项目状态");
            record.setId(obj.getString("ProjectID"));
            record.setRepairState(repairState);
            repairTaskMapper.updateByPrimaryKeySelective(record);
        } else if (2 == type) {
            RecodeTask recodeTask = new RecodeTask();
            DomainInitUtil.initUpdateDomain(recodeTask, "更换维修项目状态");
            recodeTask.setId(obj.getString("ProjectID"));
            recodeTask.setRepairState(repairState);
            recodeTaskMapper.updateByPrimaryKeySelective(recodeTask);
        }

    }

    /**
     * 改变非内检缺陷点的维修状态
     *
     * @param a        缺陷点数组
     * @param repairId 维修状态
     */
    private void changePipeBodyRepairState(JSONArray a, String repairId) {
        for (int i = 0; i < a.size(); i++) {
            PipeBodyDefect defect = new PipeBodyDefect();
            defect.setId(a.get(i).toString());
            DomainInitUtil.initUpdateDomain(defect, "更改维修状态");
            defect.setRepairState(repairId);
            pipeBodyDefectMapper.updateByPrimaryKeySelective(defect);
        }
    }

    /**
     * insert非内检缺陷与修复方法关系表
     *
     * @param a      缺陷点数组
     * @param bizId  表单主键ID
     * @param nodeId 节点ID
     */
    private void insertDefectRepairMethod(JSONArray a, String bizId, String nodeId) {
        PipeDefectRepairMethod dto = new PipeDefectRepairMethod();
        dto.setId(CommonUtil.getUUID());
        dto.setPipeDefectId(a.get(0).toString());//到时候考虑要不要这么做
        dto.setRepairMethodBizId(bizId);
        dto.setNodeId(nodeId);
        pbfMapper.insertDefectRepairMethod(dto);
    }

    /**
     * 更改taskInstance的状态
     *
     * @param trenchId 同沟Id
     * @param nodeId   节点Id
     */
    private void updateTaskInstanceStatus(String trenchId, String nodeId, boolean isChangePipe) {
        TaskInstance taskInstance = new TaskInstance();
        DomainInitUtil.initUpdateDomain(taskInstance, "更改状态");
        List<Map<String, Object>> mapList = pbfMapper.selectDefectIdBytrenchId(trenchId);
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> mapMark = mapList.get(i);
            String defectId = mapMark.get("defectId").toString();
            taskInstance.setDefectInfoId(defectId);
            taskInstance.setNodeId(nodeId);
            taskInstance.setIsCompletion((short) 1);//该节点已完成

            TaskInstanceExample example = new TaskInstanceExample();
            example.createCriteria().andDefectInfoIdEqualTo(defectId)
                    .andNodeIdEqualTo(nodeId);
            List<TaskInstance> taskInstanceList = taskInstanceMapper.selectByExample(example);
            //todo 加此代码主要是因为现在设计居然是明明任务已经建好了，结果运行到中途结果可以更改方法里面的节点
            //治根不治本 只能解决不报错的问题
            if (ObjectUtil.isEmptyAll(taskInstanceList)) {
                return;
            }
            Short sort = taskInstanceList.get(0).getSort();

            if (!isChangePipe) {//非待换管的缺陷点对于taskInstance特殊处理
                taskInstance.setSort(sort);
            }
            pbfMapper.updateTaskInstanceStatus(taskInstance);
            taskInstance.setJumpNode((short) 1);
            taskInstance.setIsCompletion((short) 0);
            pbfMapper.updateTaskInstanceJump(taskInstance);

        }

    }

    /**
     * 根据缺陷点跟新taskinstance状态
     *
     * @param defectId
     * @param nodeId
     */
    private void updateTaskInstanceStatusByDefectId(String defectId, String nodeId,boolean isChangePipe) {
        TaskInstance taskInstance = new TaskInstance();
        DomainInitUtil.initUpdateDomain(taskInstance, "更改状态至已完成");
        taskInstance.setDefectInfoId(defectId);
        taskInstance.setNodeId(nodeId);
        taskInstance.setIsCompletion((short) 1);//该节点已完成

        TaskInstanceExample example = new TaskInstanceExample();
        example.createCriteria().andDefectInfoIdEqualTo(defectId)
                .andNodeIdEqualTo(nodeId);
        List<TaskInstance> taskInstanceList = taskInstanceMapper.selectByExample(example);
        if (ObjectUtil.isEmptyAll(taskInstanceList)) {
            return;
        }
        Short sort = taskInstanceList.get(0).getSort();

        if (!isChangePipe) {//非待换管的缺陷点对于taskInstance特殊处理
            taskInstance.setSort(sort);
        }
        pbfMapper.updateTaskInstanceStatus(taskInstance);
        taskInstance.setJumpNode((short) 1);
        taskInstance.setIsCompletion((short) 0);
        pbfMapper.updateTaskInstanceJump(taskInstance);
    }

}

class DomainInitUtil {

    /**
     * 初始化domain其中的createDate、id(UUID)
     *
     * @param domainObj
     * @return
     */
    public static void initCreateDomain(Object domainObj) {
        initCreateDomain(domainObj, null);
    }

    public static void initCreateDomain(Object domainObj, String remark) {

        //  DomainFieldReflectUtil.setFieldValue(domainObj, "id", CommonUtil.getUUID());
        DomainFieldReflectUtil.setFieldValue(domainObj, "createDate", new Date());
        if (StringUtils.isNotEmpty(remark)) {
            DomainFieldReflectUtil.setFieldValue(domainObj, "createRemark", remark);
        }

    }

    /**
     * 初始化domain其中的updateDate、updateUser
     *
     * @param domainObj
     * @return
     */
    public static void initUpdateDomain(Object domainObj) {
        initUpdateDomain(domainObj, null);
    }


    /**
     * 初始化domain其中的updateDate、updateUser、updateRemark
     *
     * @param domainObj
     * @param remark
     */
    public static void initUpdateDomain(Object domainObj, String remark) {

//        UserSessionVO sessionVO= SessionCacheSupport.getSessionVO();
//        String userid = sessionVO.getId();

        DomainFieldReflectUtil.setFieldValue(domainObj, "updateDate", new Date());
        if (StringUtils.isNotEmpty(remark)) {
            DomainFieldReflectUtil.setFieldValue(domainObj, "updateRemark", remark);
        }

    }


}


